use raft4rs::server::Server;
use std::sync::Arc;
use tracing::{debug, info};
mod config;
use config::*;
use opentelemetry::api::Provider;
use opentelemetry::sdk;
use std::env;
use tracing_subscriber::prelude::*;

#[async_std::main]
async fn main() {
    init_tracer().unwrap();

    //init_log();

    let args: Vec<String> = env::args().collect();

    match args[1].as_str() {
        "1" => raft1().await,
        "2" => raft2().await,
        "3" => raft3().await,
        _ => panic!("out type"),
    }
}

fn init_tracer() -> Result<(), Box<dyn std::error::Error>> {
    let exporter = opentelemetry_jaeger::Exporter::builder()
        .with_agent_endpoint("127.0.0.1:6831".parse().unwrap())
        .with_process(opentelemetry_jaeger::Process {
            service_name: "raft_example".to_string(),
            tags: Vec::new(),
        })
        .init()?;
    let provider = sdk::Provider::builder()
        .with_simple_exporter(exporter)
        .with_config(sdk::Config {
            default_sampler: Box::new(sdk::Sampler::AlwaysOn),
            ..Default::default()
        })
        .build();
    let tracer = provider.get_tracer("tracing");

    let opentelemetry = tracing_opentelemetry::layer().with_tracer(tracer);
    tracing_subscriber::registry()
        .with(opentelemetry)
        .try_init()?;

    Ok(())
}

async fn raft1() {
    debug!("start............");

    std::thread::spawn(|| {
        let guard = pprof::ProfilerGuard::new(100).unwrap();
        if let Ok(report) = guard.report().build() {
            std::thread::sleep(std::time::Duration::from_secs(100));
            if let Ok(report) = guard.report().build() {
                println!("report: {}", &report);
            };
        };
    });

    let server1 = Arc::new(Server::new(make_config(1), make_resolver())).start();

    let replicas = &vec![1, 2, 3];

    let raft1 = server1
        .create_raft(1, 0, 1, replicas, MySM { id: 1 })
        .await
        .unwrap();
    // while !raft1.is_leader().await {
    //     if let Err(e) = raft1.try_to_leader().await {
    //         info!("raft1 try to leader has err:{:?}", e);
    //     }
    //     std::thread::sleep(std::time::Duration::from_secs(1));
    //     info!("wait raft1 to leader times");
    // }

    // let result = raft1.execute(vec![1, 2, 3], true).await.unwrap();
    // println!("execute raf1:{}", String::from_utf8(result).unwrap());

    // for i in 0..1000000u32 {
    //     if let Err(e) = raft1
    //         .submit(
    //             unsafe { format!("commit: {}", i + 1).as_mut_vec().clone() },
    //             true,
    //         )
    //         .await
    //     {
    //         println!("{:?}", e);
    //         std::thread::sleep(std::time::Duration::from_secs(1));
    //     }
    // }

    println!("raft1:{:?}", raft1.info().await);

    std::thread::sleep(std::time::Duration::from_secs(10000));
}

async fn raft2() {
    debug!("start............");

    let server2 = Arc::new(Server::new(make_config(2), make_resolver())).start();

    let replicas = &vec![1, 2, 3];

    let raft2 = server2
        .create_raft(1, 0, 1, replicas, MySM { id: 2 })
        .await
        .unwrap();

    // let result = raft2.execute(vec![2, 2, 3], true).await.unwrap();
    // println!("execute raf1:{}", String::from_utf8(result).unwrap());

    // for i in 0..1000000u32 {
    //     if let Err(e) = raft2
    //         .submit(
    //             unsafe { format!("commit: {}", i + 1).as_mut_vec().clone() },
    //             true,
    //         )
    //         .await
    //     {
    //         println!("{:?}", e);
    //         std::thread::sleep(std::time::Duration::from_secs(1));
    //     }
    // }

    println!("raft2:{:?}", raft2.info().await);

    std::thread::sleep(std::time::Duration::from_secs(10000));
}

async fn raft3() {
    debug!("start............");

    let server3 = Arc::new(Server::new(make_config(3), make_resolver())).start();

    let replicas = &vec![1, 2, 3];

    let raft3 = server3
        .create_raft(1, 0, 1, replicas, MySM { id: 3 })
        .await
        .unwrap();

    while raft3.leader() == 0 {
        std::thread::sleep(std::time::Duration::from_secs(1));
        println!("wait raft3 has leader");
    }

    let result = raft3.execute(vec![3, 2, 3], true).await.unwrap();
    println!("execute raft3:{}", String::from_utf8(result).unwrap());

    for i in 0..10000000u32 {
        if let Err(e) = raft3
            .submit(
                unsafe { format!("commit: {}", i + 1).as_mut_vec().clone() },
                true,
            )
            .await
        {
            println!("{:?}", e);
            std::thread::sleep(std::time::Duration::from_secs(1));
        }
    }

    println!("raft3:{:?}", raft3.info().await);

    std::thread::sleep(std::time::Duration::from_secs(10000));
}
